package com.fingard.dsp.bankset;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.fingard.dsp.bank.reqrespobj.PacketType;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;

public class BankFrontBalance {

    public List<BankFront> listBankFront = null;
    private HashMap<String, Integer> mapBfIndex = null;
    private int pollingIndex = -1;

    public BankFrontBalance() {
        listBankFront = new ArrayList<BankFront>();
        mapBfIndex = null;
    }

    public BankFront getBankFrontByURID(String p_urid) {
        if (listBankFront == null) {
            return null;
        }
        if (mapBfIndex == null || mapBfIndex.size() != listBankFront.size()) {
            mapBfIndex = new HashMap<String, Integer>();
            for (int i = 0; i < listBankFront.size(); i++) {
                mapBfIndex.put(listBankFront.get(i).urid, i);
            }
        }
        if (mapBfIndex.containsKey(p_urid)) {
            return listBankFront.get(mapBfIndex.get(p_urid));
        }
        return null;
    }

    public void removeBankFrontByURID(String p_urid) {
        if (listBankFront == null) {
            return;
        }
        if (mapBfIndex == null || mapBfIndex.size() != listBankFront.size()) {
            mapBfIndex = new HashMap<String, Integer>();
            for (int i = 0; i < listBankFront.size(); i++) {
                mapBfIndex.put(listBankFront.get(i).urid, i);
            }
        }
        if (mapBfIndex.containsKey(p_urid)) {
            int idx = mapBfIndex.get(p_urid);
            if (listBankFront.size() > idx) {
                listBankFront.remove(idx);
            }
        }
    }

    public BankFront getBankFrontByBalance(ReqRespHeader p_header) {
        if (listBankFront == null) {
            return null;
        }
        if (listBankFront.size() == 1) {
            BankFront retBankFront = listBankFront.get(0);
            if (retBankFront.isSupport(p_header.transType)) {
                return retBankFront;
            } else {
                return null;
            }
        }

        //策略
        //1、取可用并发数最大的
        //2、如果不限制并发数，取当前并发数最小的
        //将上面1和2取得的前置机组合在一起，采用轮询机制返回前置机
        HashMap<String, Integer> mapFor1 = new HashMap<String, Integer>();
        HashMap<String, Integer> mapFor2 = new HashMap<String, Integer>();
        int maxAvail = Integer.MIN_VALUE;
        int minConcu = Integer.MAX_VALUE;

        for (int i = 0; i < listBankFront.size(); i++) {
            BankFront eachBF = listBankFront.get(i);
            if (!eachBF.isSupport(p_header.transType)) {
                continue;
            }
            //if(retBF.frontStatus.status != EnBfStatus.exception && eachBF.frontStatus.status == EnBfStatus.normal){
            //}
            int concu = 0;
            int syncCount = 0;
            if (p_header.pckType == PacketType.Pay) {
                syncCount = eachBF.frontPayMaxCcCount;
                concu = eachBF.getPayConcurrent();
            } else if(p_header.pckType == PacketType.Ele){
                syncCount = eachBF.frontEleMaxCcCount;
                concu = eachBF.getEleConcurrent();
            }else if(p_header.pckType == PacketType.EleQuery){
                syncCount = eachBF.frontEleQueryMaxCcCount;
                concu = eachBF.getEleQryConcurrent();
            }else {
                syncCount = eachBF.frontQueryMaxCcCount;
                concu = eachBF.getQryConcurrent();
            }
            if (syncCount <= 0) {//无并发数限制
                if (concu <= minConcu) {
                    minConcu = concu;
                    mapFor2.put(eachBF.urid, concu);
                }
            } else {
                int avail = syncCount - concu;
                if (avail >= maxAvail) {
                    maxAvail = avail;
                    mapFor1.put(eachBF.urid, avail);
                }
            }
        }

        //1、取可用并发数最大的mapFor1
        //2、如果不限制并发数，取当前并发数最小的mapFor2
        //将上面1和2取得的前置机组合在一起，采用轮询机制返回前置机
        HashMap<String, Integer> mapJoin = new HashMap<String, Integer>();
        Iterator<String> it = mapFor1.keySet().iterator();
        while (it.hasNext()) {
            String urid = it.next();
            int avail = mapFor1.get(urid);
            if (avail >= maxAvail) {
                mapJoin.put(urid, avail);
            }
        }
        it = mapFor2.keySet().iterator();
        while (it.hasNext()) {
            String urid = it.next();
            int concu = mapFor2.get(urid);
            if (concu <= minConcu) {
                mapJoin.put(urid, concu);
            }
        }

        //轮询
        for (int i = 0; i < listBankFront.size(); i++) {
            pollingIndex++;
            pollingIndex = pollingIndex % listBankFront.size();
            BankFront trgBF = listBankFront.get(pollingIndex);
            if (mapJoin.containsKey(trgBF.urid)) {
                return trgBF;
            }
        }

        for (int i = 0; i < listBankFront.size(); i++) {
            BankFront eachBF = listBankFront.get(i);
            if (eachBF.isSupport(p_header.transType)) {
                return eachBF;
            }
        }
        return null;
    }
}
